Water Index · Surface Water Detection

NDWI – Normalized Difference Water Index

NDWI (McFeeters, 1996) is a water index designed to enhance open water features using Green and NIR reflectance, and to suppress vegetation and soil background.

1. Scientific Definition

The Normalized Difference Water Index (NDWI) is a spectral index that highlights open surface water bodies (lakes, rivers, reservoirs) and suppresses vegetation and bare soil.

Formula (McFeeters 1996)

NDWI = (Green − NIR) / (Green + NIR) Range: −1 → +1

  • Green: Green band reflectance
  • NIR: Near-InfraRed reflectance

Typical Interpretation

NDWI ValueInterpretation
< 0Soil, built-up areas, vegetation, dry surfaces
0 – 0.1Very humid soil / mixed land–water pixels
0.1 – 0.3Shallow water / turbid water / wetlands
> 0.3Open deep water / clear water bodies

Key Applications

  • Water bodies detection & extraction
  • Flood mapping
  • Monitoring lakes, reservoirs, rivers
  • Change detection of water extent over time

2. Data & Bands for NDWI

Sentinel-2 (ESA)

  • Green: B3 (~560 nm)
  • NIR: B8 (~842 nm)

Landsat 8/9 OLI

  • Green: B3
  • NIR: B5

Best Practices

  • Use surface reflectance products (SR collections).
  • Mask clouds and cloud shadows carefully.
  • Use consistent thresholds for water vs. non-water (e.g., NDWI > 0.3 → water).
  • Optionally combine with MNDWI or NDWI(Gao) for specific applications.

Suggested Palette

Example palette for NDWI water mapping: [ "#1d1b4c", "#20639b", "#28a6d9", "#52d1ff", "#e0f9ff" ]

3. Google Earth Engine Code – NDWI (McFeeters, Green–NIR)

// NDWI (McFeeters 1996) using Sentinel-2 SR
// NDWI = (Green - NIR) / (Green + NIR)

var roi = geometry;   // Draw your AOI and rename to 'geometry'
Map.centerObject(roi, 11);

// 1. Load Sentinel-2 surface reflectance
var s2 = ee.ImageCollection("COPERNICUS/S2_SR")
  .filterBounds(roi)
  .filterDate("2023-01-01", "2023-12-31")
  .filter(ee.Filter.lt("CLOUDY_PIXEL_PERCENTAGE", 20))
  .select(["B3","B8"]); // Green (B3), NIR (B8)

// 2. Create a median composite
var img = s2.median().clip(roi);

// 3. Compute NDWI
var ndwi = img.expression(
  "(G - N) / (G + N)",
  {
    "G": img.select("B3"),
    "N": img.select("B8")
  }
).rename("NDWI");

// 4. Visualization
var ndwiVis = {
  min: -1,
  max: 1,
  palette: [
    "#1d1b4c", // deep water
    "#20639b",
    "#28a6d9",
    "#52d1ff",
    "#e0f9ff"  // shallow/wet surfaces
  ]
};

Map.addLayer(ndwi, ndwiVis, "NDWI (Green-NIR)");

// Optional: show true color for reference
var rgb = ee.ImageCollection("COPERNICUS/S2_SR")
  .filterBounds(roi)
  .filterDate("2023-01-01", "2023-12-31")
  .filter(ee.Filter.lt("CLOUDY_PIXEL_PERCENTAGE", 20))
  .select(["B4","B3","B2"])
  .median()
  .clip(roi);

Map.addLayer(rgb, {min:0, max:3000}, "True Color", false);

// 5. Export NDWI as GeoTIFF
Export.image.toDrive({
  image: ndwi,
  description: "NDWI_Export",
  fileNamePrefix: "NDWI_Green_NIR",
  region: roi,
  scale: 10,        // Sentinel-2 native resolution for B3/B8
  crs: "EPSG:4326",
  maxPixels: 1e13
});